home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / ai / tierra40 / tierra / genio.c < prev    next >
C/C++ Source or Header  |  1992-09-08  |  29KB  |  910 lines

  1. /* genio.c   9-9-92 genebank input/output routines */
  2. /* Tierra Simulator V4.0: Copyright (c) 1991, 1992 Tom Ray & Virtual Life */
  3.  
  4. #ifndef lint
  5. static char sccsid[] = "@(#)genio.c    1.5 7/21/92";
  6. #endif
  7.  
  8. #include "license.h"
  9. #include "tierra.h"
  10. #include "extern.h"
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #include <errno.h>
  14.  
  15. #ifdef MEM_CHK
  16. #include <memcheck.h>
  17. #endif
  18.  
  19. #define WritEcoS(bits)                WritEcoB(bits, mes[9])
  20.  
  21. /*
  22.  * open_ar - open a genebank archive
  23.  *
  24.  *     file - the filename;
  25.  *     size - the creature size
  26.  *     format - a byte, usually the instruction set number
  27.  *     mode - 0 if the file exists its contents should be preserved,
  28.  *            < 0, if doesn't exit create it
  29.  *              else if the file should be created (or truncated). mode > 1
  30.  *              is taken as the number of index entries to allocate
  31.  *            (will be rounded to the next highest # such that
  32.  *            index + header is a multiple of 1K)
  33.  *
  34.  * returns a pointer to a file opened for update, or NULL if unsuccessful.
  35.  * open_ar fails if size or format are incompatible with the archive.
  36.  */
  37.  
  38. FILE *open_ar(file, size, format, mode)
  39.     I8s *file;
  40.     I32s size, mode, format;
  41. {
  42.     FILE *fp = NULL;
  43.     head_t head;
  44.     struct stat buf; 
  45.  
  46.     if (( mode > 0) || (mode < 0 && (stat(file, &buf) == -1)))
  47.     {   if (mode < 0) /* if file doesn't exist, no entries */
  48.             mode = 0;
  49.         if (fp = fopen(file, "w+b"))
  50.         {   strcpy(head.magic, "tie");
  51.             head.magic[3] = '0' + format;
  52.             head.size = size;
  53.             head.n = 0;
  54.             head.n_alloc = (((int) ((sizeof(head_t) + mode * sizeof(indx_t)) /
  55.                       1024.0) + 1) * 1024 - sizeof head) / sizeof(indx_t);
  56.             head.g_off = sizeof(head_t) + head.n_alloc * sizeof(indx_t);
  57.             write_head(fp, &head);
  58.         }
  59.     }
  60.     else if (mode < 1 && (fp = fopen(file, "r+b")))
  61.     {   head = read_head(fp);
  62.         if (head.size != size || (format > -1) && head.magic[3] !=
  63.             format + '0' || strncmp(head.magic, "tie", 3))
  64.         {   fclose(fp);
  65.             fp = NULL;
  66.             errno = EINVAL;
  67.         }
  68.     }
  69.     return fp;
  70. }
  71.  
  72. /*
  73.  * read_head - read header from a genebank archive
  74.  */
  75.  
  76. head_t read_head(fp)
  77.     FILE *fp;
  78. {
  79.     head_t t;
  80.  
  81.     if ((fp != NULL) && !fseek(fp, 0, 0))
  82.         fread(&t, sizeof(head_t), 1, fp);
  83.     else
  84.     {
  85. #ifdef ARG
  86.         fprintf(stderr, "Tierra read_head() file access failed");
  87.         exit(errno);
  88. #else
  89.         FEError(-400,EXIT,NOWRITE, "Tierra read_head() file access failed");
  90. #endif
  91.     }
  92.     if (GFormat < 0) 
  93.         GFormat = t.magic[3] -'0';        /* autoselect */
  94.     return t;
  95. }
  96.  
  97. /*
  98.  * write_head - write header to a genebank archive
  99.  */
  100.  
  101. void write_head(fp, head)
  102.     FILE *fp;
  103.     head_t *head;
  104. {
  105.     if (!fseek(fp, 0, 0))
  106.         fwrite(head, sizeof(head_t), 1, fp);
  107.     else
  108.     {
  109. #ifdef ARG
  110.         fprintf(stderr, "Tierra write_head() file access failed");
  111.         exit(errno);
  112. #else
  113.         FEError(-401,EXIT,NOWRITE, "Tierra write_head() file access failed");
  114. #endif
  115.     }
  116. }
  117.  
  118. /*
  119.  * read_indx - read the index from a genebank archive
  120.  */
  121.  
  122. indx_t *read_indx(fp, head)
  123.     FILE *fp;
  124.     head_t *head;
  125. {
  126. #ifdef ERROR
  127.     I32s  i;
  128. #endif /* ERROR */
  129.     indx_t *t = 0;
  130.  
  131. #ifdef __TURBOC__ 
  132.     t = &GIndx;
  133. #else /* __TURBOC__ */
  134.     if (!fseek(fp, sizeof(head_t), 0))
  135.     {   t = (indx_t *) thcalloc(head->n_alloc, sizeof(indx_t));
  136.         if (t != NULL)
  137.             fread(t, sizeof(indx_t), head->n, fp);
  138.     }
  139.     else
  140.     {
  141. #ifdef ARG
  142.         fprintf(stderr, "Tierra read_index() file access failed");
  143.         exit(errno);
  144. #else /* ARG */
  145.         FEError(-402,EXIT,NOWRITE, "Tierra read_index() file access failed");
  146. #endif /* ARG */
  147.     }
  148. #ifdef ERROR
  149.     if (t != NULL)
  150.         for (i = 0; i < head->n; i++)
  151.             if (!(t + i)->psize)
  152. #ifdef ARG
  153.             {   fprintf(stderr, "Tierra read_index() indx array corrupted");
  154.                 exit(errno);
  155.             }
  156. #else  /* ARG */
  157.                 FEError(-403,EXIT,NOWRITE,
  158.                     "Tierra read_index() indx array corrupted");
  159. #endif /* ARG */
  160. #endif /* ERROR */
  161. #endif /* __TURBOC__ */
  162.     return t;
  163. }
  164.  
  165. /*
  166.  * write_indx - write the index to a genebank archive
  167.  */
  168.  
  169. void write_indx(fp, head, indx)
  170.     FILE *fp;
  171.     head_t *head;
  172.     indx_t *indx;
  173. {
  174. #ifdef ERROR
  175.     I32s  i;
  176. #endif /* ERROR */
  177. #ifdef __TURBOC__ 
  178.     return ;
  179. #endif /* __TURBOC__ */
  180.  
  181. #ifdef ERROR
  182.     for (i = 0; i < head->n; i++)
  183.         if (!(indx + i)->psize)
  184. #ifdef ARG
  185.         {   fprintf(stderr, "Tierra write_index() indx array corrupted");
  186.             exit(errno);
  187.         }
  188. #else  /* ARG */
  189.             FEError(-404,EXIT,NOWRITE,
  190.                 "Tierra write_index() indx array corrupted");
  191. #endif /* ARG */
  192. #endif /* ERROR */
  193.     if (!fseek(fp, sizeof(head_t), 0))
  194.         fwrite(indx, sizeof(indx_t), head->n_alloc, fp);
  195.     else
  196.     {
  197. #ifdef ARG
  198.         fprintf(stderr, "Tierra write_index() file access failed");
  199.         exit(errno);
  200. #else
  201.         FEError(-405,EXIT,NOWRITE, "Tierra write_index() file access failed");
  202. #endif
  203.     }
  204. }
  205.  
  206. /*
  207.  * find_gen - find the index of a genome in an archive by its 3 letter name
  208.  *
  209.  * will return n (number of genomes) if not found, otherwise the position
  210.  * (0 - n-1) in archive
  211.  */
  212.  
  213. I32s find_gen(fp, indx, gen, n)
  214.     FILE    *fp;
  215.     indx_t  *indx;
  216.     I8s     *gen;
  217.     I32s    n;
  218. {
  219.     I32s i;
  220.  
  221. #ifdef __TURBOC__
  222.     if (!strncmp("---", gen, 3))
  223.     {   fseek(fp, sizeof(head_t) + (n * sizeof(indx_t)), 0);
  224.         fread(indx, sizeof(indx_t), 1, fp);
  225.         i = n;
  226.     }
  227.     else
  228.     {   fseek(fp, sizeof(head_t), 0);      /* seek past head */
  229.         for(i = 0; i < n; i++)       /* scan index for gen */
  230.         {   fread(indx, sizeof(indx_t), 1, fp);
  231.             if (!strncmp(indx->gen, gen, 3))
  232.                 break;
  233.         }
  234.     }
  235. #else /* __TURBOC__ */
  236.     for (i = 0; i < n; i++)
  237.         if (!strncmp((indx + i)->gen, gen, 3))
  238.             break;
  239. #endif /* __TURBOC__ */
  240.     return i;
  241. }
  242.  
  243. /*
  244.  * get_gen - read a genome from genebank archive and return a pointer
  245.  *     to a struct g_list containing all saved info.
  246.  *
  247.  *     fp - pointer to open archive file
  248.  *     head - archive header
  249.  *     indxn - index entry of desired genome
  250.  *     n - position of desired genome in archive
  251.  *
  252.  * reads the genome and reformats its other args into the form used
  253.  * internally by tierra. the genotype must be in archive. n can be
  254.  * determined by find_gen(). currently no error checking
  255.  */
  256.  
  257. Pgl get_gen(fp, head, indxn, n)
  258.     FILE *fp;
  259.     indx_t *indxn;
  260.     head_t *head;
  261.     I32s n;
  262. {   
  263.     Pgl t = (Pgl) tcalloc(1, sizeof(GList));
  264.     fseek(fp, head->g_off +
  265.           (n * head->size * (sizeof(Instruction) + sizeof(GenBits))), 0);
  266.     t->genome = (FpInst) tcalloc(head->size, sizeof(Instruction));
  267.     t->gbits = (FpGenB) tcalloc(head->size, sizeof(GenBits));
  268.     fread(t->genome, head->size * sizeof(Instruction), 1, fp);
  269.     fread(t->gbits, head->size * sizeof(GenBits), 1, fp);
  270.     t->gen.size = head->size;
  271.     strncpy(t->gen.label, indxn->gen, 3);
  272.     t->parent.size = indxn->psize;
  273.     strncpy(t->parent.label, indxn->pgen, 3);
  274.     t->bits = indxn->bits;
  275.     t->hash = indxn->hash;
  276.     t->d1 = indxn->d1;
  277.     t->d2 = indxn->d2;
  278.     t->originI = indxn->originI;
  279.     t->originC = indxn->originC;
  280.     t->MaxPropPop = (float) indxn->mpp / 10000.;
  281.     t->MaxPropInst = (float) indxn->mpi / 10000.;
  282.     t->mpp_time = indxn->mppT;
  283.     t->ploidy = (indxn->pt & 0360) >> 4;
  284.     t->track = indxn->pt & 017;
  285.     return t;
  286. }
  287.  
  288. /*
  289.  * add_gen - replace or add a genotype to end of genebank archive
  290.  *
  291.  *     fp - pointer to open archive file
  292.  *     head - header of archive
  293.  *     indx - index of archive
  294.  *     gen - genotype to be added
  295.  *
  296.  * reformats the genotype and replaces it in the archive, or adds it to
  297.  * the end if not found. args head & indx are modified by this fn.
  298.  * returns 0 on add, and 1 on replace.
  299.  *
  300.  * Scheme of add_gen():
  301.  *
  302.  * 1) find the gen in the file, or find out if it is not in the file.
  303.  *    This may be done with find_gen() if we have indx in RAM, or by
  304.  *    by repeated freads if we don't have indx.
  305.  * 2) If gen is not in file and file is full, we must enlarge the file by
  306.  *    moving the genotypes out to make room for more indexes.
  307.  *    Three strategies are used here.  In Unix, we read the entire index
  308.  *    and bank of genomes into RAM, then write them back out into their
  309.  *    new locations.  In DOS, when memory is available, we will copy
  310.  *    the genomes one by one from their old to their new locations on disk,
  311.  *    then we write the free index structures over with zeros.  In DOS
  312.  *    when memory is not available, we copy the genomes byte by byte.
  313.  * 3) We write the new genome and genbits to the file.
  314.  * 4) We determine if this was an add or a replace.
  315.  * 5) We write the new updated head.
  316.  * 6) We update the index of the new gen in RAM.
  317.  * 7) We write the new index to the file.
  318.  * 8) We return add or replace.
  319.  *
  320.  */
  321.  
  322. I32s add_gen(fp, head, indx, gen)
  323.     FILE *fp;
  324.     head_t *head;
  325.     indx_t **indx;
  326.     Pgl gen;
  327. {
  328.     I8s     t_buf = '\0';
  329.     I32s    n, s, ret, oldoff, gensiz, old_n_alloc, i;
  330.     I32s    wsiz = 0, rsiz = 0, segs, rem;
  331.     indx_t  t_indx, *tp_indx, *tindx;
  332. #ifdef __TURBOC__
  333.     I8s     buf[512];
  334. #else  /* __TURBOC__ */
  335.     I8s     *buf;
  336. #endif /* __TURBOC__ */
  337.  
  338.     Swap = 0; /* to avoid recursion */
  339.     gensiz = (head->size * (sizeof(Instruction) + sizeof(GenBits)));
  340.  
  341. /* 1) find the gen in the file, or find out if it is not in the file.
  342.  *    This may be done with find_gen() if we have indx in RAM, or by
  343.  *    by repeated freads if we don't have indx.  */
  344.  
  345.     n = find_gen(fp, *indx, gen->gen.label, head->n); /* does not alloc */
  346.  
  347. /* 2) If gen is not in file and file is full, we must enlarge the file by
  348.  *    moving the genotypes out to make room for more indexes.
  349.  *    Three strategies are used here.  In Unix, we read the entire index
  350.  *    and bank of genomes into RAM, then write them back out into their
  351.  *    new locations.  In DOS, when memory is available, we will copy the
  352.  *    genomes one by one from their old to their new locations on disk,
  353.  *    then we write over with zeros, the free index structures.  In DOS
  354.  *    when memory is not available, we copy the genomes byte by byte. */
  355.  
  356.     /* n == head->n means not in index */
  357.     /* head->n == head->n_alloc means file is full */
  358.     /* if not in file and file is full */
  359.     if (n == head->n && head->n == head->n_alloc)
  360.     {   old_n_alloc = head->n_alloc;
  361.         head->n_alloc += 1024 / sizeof(indx_t);
  362.         oldoff = head->g_off;
  363.         head->g_off = sizeof(head_t) + (head->n_alloc * sizeof(indx_t));
  364. #ifdef __TURBOC__
  365.         fseek(fp, 0, SEEK_END); /* make room at end for slide */
  366.         fwrite(&t_buf, sizeof(I8s), head->g_off - oldoff, fp);/* write zeros*/
  367.         segs = (gensiz * head->n) / 512;
  368.         rem  = (gensiz * head->n) % 512;
  369.         if (rem)
  370.         {   fseek(fp, (segs * 512) + oldoff, 0);
  371.             rsiz += fread(buf, sizeof(I8s), rem, fp);
  372.             fseek(fp, (segs * 512) + head->g_off, 0);
  373.             wsiz += fwrite(buf, sizeof(I8s), rem, fp);
  374.         }
  375.         if (segs) for(i = segs - 1; i >= 0; i--)
  376.         {   fseek(fp, (i * 512) + oldoff, 0);
  377.             rsiz += fread(buf, sizeof(I8s), 512, fp);
  378.             fseek(fp, (i * 512) + head->g_off, 0);
  379.             wsiz += fwrite(buf, sizeof(I8s), 512, fp);
  380.         }
  381. #ifdef ERROR
  382.         if ((rsiz != gensiz * head->n) || (wsiz != gensiz * head->n))
  383. #ifdef ARG
  384.         {   fprintf(stderr, "Tierra add_gen() rsiz or wsiz bad");
  385.             exit(errno);
  386.         }
  387. #else  /* ARG */
  388.             FEError(-406,EXIT,NOWRITE, "Tierra add_gen() rsiz or wsiz bad");
  389. #endif /* ARG */
  390. #endif /* ERROR */
  391. #else  /* __TURBOC__ */
  392.         fseek(fp, oldoff, 0);
  393.         buf = (I8s *) thcalloc(s = gensiz * head->n , 1);
  394.         fread(buf, s, 1, fp);
  395.         fseek(fp, head->g_off, 0);
  396.         fwrite(buf, s, 1, fp);
  397.         if (buf)
  398.         {   thfree(buf);
  399.             buf = NULL;
  400.         }
  401.         tindx = (indx_t *) threcalloc(*indx,
  402.             sizeof(indx_t) * head->n_alloc,
  403.             sizeof(indx_t) * old_n_alloc);
  404.         if (tindx)
  405.         {   *indx = tindx;
  406.             for (i = old_n_alloc * sizeof(indx_t);
  407.                 i < head->n_alloc * sizeof(indx_t); i++)
  408.                 ((I8s  *) *indx)[i] = (I8s) 0;
  409.         }
  410.         else if (*indx)
  411.         {   thfree(*indx);
  412.             *indx = NULL;
  413.         }
  414. #endif /* __TURBOC__ */
  415.     }
  416.  
  417. /* 3) We write the new genome and genbits to the file. */
  418.  
  419.     fseek(fp, head->g_off + (n * gensiz), 0);
  420.     fwrite(gen->genome, head->size * sizeof(Instruction), 1, fp);
  421.     fwrite(gen->gbits, head->size * sizeof(GenBits), 1, fp);
  422.  
  423. /* 4) We determine if this was an add or a replace. */
  424.  
  425.     head->n += ret = (n == head->n);
  426.  
  427. /* 5) We write the new updated head. */
  428.  
  429.     write_head(fp, head); /* no alloc */
  430.  
  431. /* 6) We update the index of the new gen in RAM. */
  432.  
  433. #ifdef __TURBOC__
  434.     tp_indx = *indx; /* fake pointers for meat of function */
  435. #else  /* __TURBOC__ */
  436.     tp_indx = &((*indx)[n]);
  437. #endif /* __TURBOC__ */
  438.     strncpy((tp_indx)->gen, gen->gen.label, 3);
  439.     (tp_indx)->psize = gen->parent.size;
  440.     strncpy((tp_indx)->pgen, gen->parent.label, 3);
  441.     (tp_indx)->bits = gen->bits;
  442.     (tp_indx)->hash = gen->hash;
  443.     (tp_indx)->d1 = gen->d1;
  444.     (tp_indx)->d2 = gen->d2;
  445.     (tp_indx)->originI = gen->originI;
  446.     (tp_indx)->originC = gen->originC;
  447.     (tp_indx)->mpp = (short) (gen->MaxPropPop * 10000);
  448.     (tp_indx)->mpi = (short) (gen->MaxPropInst * 10000);
  449.     (tp_indx)->mppT =  (gen->mpp_time);
  450.     (tp_indx)->pt = (gen->ploidy << 4) + gen->track;
  451.  
  452. /* 7) We write the new index to the file. */
  453.  
  454. #ifdef ERROR
  455. #ifdef __TURBOC__
  456.     if (!tp_indx->psize)
  457. #ifdef ARG
  458.     {   fprintf(stderr, "Tierra add_gen() tp_indx corrupted");
  459.         exit(errno);
  460.     }
  461. #else  /* ARG */
  462.         FEError(-407,EXIT,NOWRITE, "Tierra add_gen() tp_indx corrupted");
  463. #endif /* ARG */
  464. #else /* __TURBOC__ */
  465.     for (i = 0; i < head->n; i++)
  466.         if (!(*indx)[i].psize)
  467. #ifdef ARG
  468.         {   fprintf(stderr, "Tierra add_gen() indx array corrupted");
  469.             exit(errno);
  470.         }
  471. #else  /* ARG */
  472.             FEError(-408,EXIT,NOWRITE,
  473.                 "Tierra add_gen() indx array corrupted");
  474. #endif /* ARG */
  475. #endif /* __TURBOC__ */
  476. #endif /* ERROR */
  477. #ifdef __TURBOC__
  478.     fseek(fp,((n * sizeof(indx_t)) + sizeof(head_t)), 0);
  479.     fwrite(tp_indx, sizeof(indx_t), 1, fp);
  480. #else /* __TURBOC__ */
  481.     write_indx(fp, head, *indx);
  482. #endif /* __TURBOC__ */
  483.  
  484. /* 8) We return add or replace. */
  485.  
  486.     Swap = 1;
  487.     return !ret;
  488. }
  489.  
  490. I16s GetAscGen(g, ifile)
  491.     Pgl g;
  492.     I8s ifile[];
  493. {
  494.     I8s bit[4], chm[4], buf[81], tbuf[81], *gdat, inst[9];
  495.     I16s t1, format;
  496.     I32s j, k, p, stl;
  497.     I8u ti, dontfgets = 1;
  498.     FILE *inf;
  499.  
  500.     inf = fopen(ifile, "r");
  501.     if (inf == NULL)
  502.     {
  503. #ifdef ARG
  504.         fprintf(stderr,"Tierra GetAscGen() file %s not opened, exiting", ifile);
  505.         exit(errno);
  506. #else
  507.         FEError(-409,EXIT,WRITE,
  508.             "Tierra GetAscGen() file %s not opened, exiting", ifile);
  509. #endif
  510.     }
  511.     gdat = (I8s *) tcalloc(85, sizeof(I8s));
  512.     g->ploidy = (I8s) 1;   /* default ploidy */
  513.     fgets(gdat, 84, inf);
  514.     while (strlen(gdat) < 3)  /* eat blank lines */
  515.         fgets(gdat, 84, inf);
  516.     while (1)
  517.     {   if (dontfgets)
  518.             dontfgets = 0;
  519.         else
  520.             fgets(gdat, 84, inf);
  521.         if (strlen(gdat) < 3) break;     /* get a blank line and break */
  522.         sscanf(gdat, "%s", buf);
  523.         if (!strcmp(buf, "format:"))
  524.         {   sscanf(gdat, "%*s%hd%*s%lu", &format, &g->bits);
  525.             if (GFormat < 0 ) GFormat = format;
  526.             continue;
  527.         }
  528.         if (!strcmp(buf, "genotype:"))
  529.         {   sscanf(gdat, "%*s%ld%s%*s%*s%ld%s", &g->gen.size,
  530.                 g->gen.label, &g->parent.size, g->parent.label);
  531.             continue;
  532.         }
  533.         if (!strcmp(buf, "1st_daughter:"))
  534.         {   sscanf(gdat, "%*s%*s%ld%*s%ld%*s%ld%*s%hd",
  535.                 &g->d1.flags, &g->d1.inst, &g->d1.mov_daught, &t1);
  536.             g->d1.BreedTrue = t1;
  537.             continue;
  538.         }
  539.         if (!strcmp(buf, "2nd_daughter:"))
  540.         {   sscanf(gdat, "%*s%*s%ld%*s%ld%*s%ld%*s%hd",
  541.                 &g->d2.flags, &g->d2.inst, &g->d2.mov_daught, &t1);
  542.             g->d2.BreedTrue = t1;
  543.             continue;
  544.         }
  545.         if (!strcmp(buf, "InstExe.m:"))
  546.         {   sscanf(gdat, "%*s%ld%%*s%ld%*s%ld",
  547.                 &g->originI.m, &g->originI.i, &g->originC);
  548.             continue;
  549.         }
  550.         if (!strcmp(buf, "MaxPropPop:"))
  551.         {   if(format < 2)
  552.                 sscanf(gdat, "%*s%f%*s%f", &g->MaxPropPop, &g->MaxPropInst);
  553.             else
  554.                sscanf(gdat, "%*s%f%*s%f%*s%ld,%ld", 
  555.                    &g->MaxPropPop, &g->MaxPropInst,
  556.                    &g->mpp_time.m, &g->mpp_time.i);
  557.             continue;
  558.         }
  559.         if (!strcmp(buf, "Origin:"))
  560.         {   sscanf(gdat, "%*s%ld,%ld%*s%ld",
  561.                 &g->originI.m, &g->originI.i, &g->originC);
  562.             continue;
  563.         }
  564.         if (!strcmp(buf, "ploidy:"))
  565.         {   sscanf(gdat, "%*s%ld%*s%ld", &j, &k);
  566.             g->ploidy = (I8s) j;
  567.             g->track = (I8s) k;
  568.             continue;
  569.         }
  570.         if (!strcmp(buf, "comments:"))
  571.         {   do
  572.             {   fgets(gdat, 84, inf);
  573.                 sscanf(gdat ,"%s", tbuf);
  574.             }   while (strlen(gdat) > 2 && tbuf[strlen(tbuf) - 1] != ':');
  575.             dontfgets = 1;
  576.         }
  577.     }
  578.     g->genome = (FpInst) tcalloc(g->gen.size, sizeof(Instruction));
  579.     g->gbits = (FpGenB) tcalloc(g->gen.size, sizeof(GenBits));
  580. #if PLOIDY == 1
  581.     fgets(gdat, 84, inf);
  582.     fgets(gdat, 84, inf);
  583.     for (j = 0; j < g->gen.size; j++)
  584.     {   fgets(gdat, 84, inf);
  585.         stl = sscanf(gdat, "%s%*s%s%s", inst, chm, bit);
  586.         if (stl > 1 && strlen(chm) == 3)
  587.         {   g->genome[j].read = chm[2] - '0';
  588.             g->genome[j].write = chm[1] - '0';
  589.             g->genome[j].exec = chm[0] - '0';
  590.         }
  591.         if (stl > 2 && strlen(bit) == 3)
  592.         {   if (bit[0] - '0') g->gbits[j] |= (I8s) 1;
  593.             if (bit[1] - '0') g->gbits[j] |= (I8s) (1 << 1);
  594.             if (bit[2] - '0') g->gbits[j] |= (I8s) (1 << 2);
  595.         }
  596.         for (k = 0; k < INSTNUM; k++)
  597.         {   if (!strcmp(inst, id[k].mn))
  598.             {   ti = id[k].op;
  599.                 break;
  600.             }
  601.         }
  602.         if (k == INSTNUM)
  603.         {
  604. #ifdef ARG
  605.            fprintf(stderr,
  606.                "Tierra GetAscGen() mnemonic %s not recognized\n", inst);
  607. #else
  608.             FEError(-410,NOEXIT,WRITE,
  609.                "Tierra GetAscGen() mnemonic %s not recognized\n", inst);
  610. #endif
  611.             ti = 0;
  612.         }
  613.         g->genome[j].inst = ti;
  614.     }
  615. #else /* PLOIDY > 1 */
  616.     for (p = 0; p < PLOIDY; p++)
  617.     {   if (p) fgets(gdat, 84, inf);
  618.         fgets(gdat, 84, inf);
  619.         fgets(gdat, 84, inf);
  620.         for (j = 0; j < g->gen.size; j++)
  621.         {   fgets(gdat, 84, inf);
  622.             stl = sscanf(gdat, "%s%*s%s%s", inst, chm, bit);
  623.             if (stl > 1 && strlen(chm) == 3)
  624.             {   g->genome[j][p].read = chm[2] - '0';
  625.                 g->genome[j][p].write = chm[1] - '0';
  626.                 g->genome[j][p].exec = chm[0] - '0';
  627.             }
  628.             if (stl > 2 && strlen(bit) == 3)
  629.             {   if (bit[0] - '0') g->gbits[j][p] |= (I8s) 1;
  630.                 if (bit[1] - '0') g->gbits[j][p] |= (I8s) (1 << 1);
  631.                 if (bit[2] - '0') g->gbits[j][p] |= (I8s) (1 << 2);
  632.             }
  633.             for (k = 0; k < INSTNUM; k++)
  634.             {   if (!strcmp(inst, id[k].mn))
  635.                 {   ti = id[k].op;
  636.                     break;
  637.                 }
  638.             }
  639.             if (k == INSTNUM)
  640.             {
  641. #ifdef ARG
  642.                 fprintf(stderr,
  643.                     "Tierra GetAscGen() mnemonic %s not recognized\n", inst);
  644. #else
  645.                 FEError(-411,NOEXIT,WRITE,
  646.                     "Tierra GetAscGen() mnemonic %s not recognized\n", inst);
  647. #endif
  648.                 ti = 0;
  649.             }
  650.             g->genome[j][p].inst = ti;
  651.         }
  652.     }
  653. #endif /* PLOIDY >  1 */
  654.     fclose(inf);
  655.     g->hash = Hash(g->gen.size, g->genome);
  656. #ifdef IBM3090
  657.     Ebcdic2Ascii(g->gen.label);
  658.     Ebcdic2Ascii(g->parent.label);
  659. #endif
  660.     if (gdat)
  661.     {   tfree(gdat);
  662.         gdat = NULL;
  663.     }
  664.     return 1;
  665. }
  666.  
  667. I8s WritAscFile(g, file)
  668.     Pgl g;
  669.     I8s *file;
  670. {
  671.     I8s bit[4], chm[4];
  672.     I16s t1;
  673.     I16u di, t, j;
  674.     I8s format = GFormat;
  675.     long int tp;
  676.     FILE *fp;
  677.  
  678. #ifdef IBM3090
  679.     I8s lbl[4], plbl[4], *comnts;
  680.  
  681. #endif
  682.     if (format < 0) format = INST;
  683.     if (!strcmp(file, "-"))
  684.         fp = stdout;
  685.     else if (!(fp = fopen(file, "w"))) {
  686. #ifdef ARG
  687.         fprintf(stderr,
  688.             "Tierra WritAscFile() unable to open WritAscFile file %s",file);
  689.         exit(errno);
  690. #else
  691.         FEError(-412,EXIT,NOWRITE,
  692.             "Tierra WritAscFile() unable to open WritAscFile file %s",file);
  693. #endif
  694.     }
  695.     WritEcoB(g->bits, mes[9]);
  696.     fprintf(fp, "\nformat: %hd  bits: %lu  %s\n", format, g->bits,mes[9]);
  697. #ifdef IBM3090
  698.     strcpy(lbl, g->gen.label);
  699.     strcpy(plbl, g->parent.label);
  700.     Ascii2Ebcdic(lbl);
  701.     Ascii2Ebcdic(plbl);
  702.     fprintf(fp, "genotype: %04ld%s  parent genotype: %04ld%s\n",
  703.             g->gen.size, lbl, g->parent.size, plbl);
  704. #else
  705.     fprintf(fp, "genotype: %04ld%s  parent genotype: %04ld%s\n",
  706.             g->gen.size, g->gen.label, g->parent.size, g->parent.label);
  707. #endif
  708.     t1 = g->d1.BreedTrue;
  709.     fprintf(fp, "1st_daughter:  flags: %ld  inst: %ld  mov_daught: %ld  \
  710.         breed_true: %hd\n", g->d1.flags, g->d1.inst, g->d1.mov_daught, t1);
  711.     t1 = g->d2.BreedTrue;
  712.     fprintf(fp, "2nd_daughter:  flags: %ld  inst: %ld  mov_daught: %ld  \
  713.         breed_true: %hd\n", g->d2.flags, g->d2.inst, g->d2.mov_daught, t1);
  714.     tp = g->originC;
  715.     if(format < 2)
  716.        {
  717.        fprintf(fp, "InstExe.m: %ld InstExe.i: %ld  origin: %ld  %s",
  718.             g->originI.m, g->originI.i, g->originC, ctime(&tp));
  719.        fprintf(fp, 
  720.        "MaxPropPop: %g  MaxPropInst: %g \n", g->MaxPropPop, g->MaxPropInst);
  721.        }
  722.     else
  723.        {
  724.        fprintf(fp, "Origin: InstExe: %ld,%ld  clock: %ld  %s",
  725.             g->originI.m, g->originI.i, g->originC, ctime(&tp));
  726.        fprintf(fp, 
  727.        "MaxPropPop: %g  MaxPropInst: %g mpp_time: %ld,%ld \n", 
  728.             g->MaxPropPop, g->MaxPropInst,g->mpp_time.m,g->mpp_time.i);
  729.         }
  730.     fprintf(fp, "ploidy: %ld  track: %ld\n", (I32s) g->ploidy,
  731.             (I32s) g->track);
  732.     fprintf(fp, "\n");
  733.     chm[3] = bit[3] = 0;
  734.  
  735. #if PLOIDY == 1
  736.         fprintf(fp, "track 0: prot\n          xwr\n" );
  737.         for (t = 0; t < g->gen.size; t++) {
  738.             di = g->genome[t].inst;
  739.             bit[0] = IsBit(g->gbits[t], 0) ? '1' : '0';
  740.             bit[1] = IsBit(g->gbits[t], 1) ? '1' : '0';
  741.             bit[2] = IsBit(g->gbits[t], 2) ? '1' : '0';
  742.             chm[0] = '0' + g->genome[t].exec;
  743.             chm[1] = '0' + g->genome[t].write;
  744.             chm[2] = '0' + g->genome[t].read;
  745.             fprintf(fp, "%-8s; %s %s %02x %3u\n", id[di].mn, chm, 
  746.                     bit, di, t);
  747.         }
  748. #else /* PLOIDY > 1 */
  749.     for (j = 0; j < PLOIDY; j++) {
  750.         if (j)
  751.             fprintf(fp, "\n");
  752.         fprintf(fp, "track %ld: prot\n          xwr\n", j);
  753.         for (t = 0; t < g->gen.size; t++) {
  754.             di = g->genome[t][j].inst;
  755.             bit[0] = IsBit(g->gbits[t][j], 0) ? '1' : '0';
  756.             bit[1] = IsBit(g->gbits[t][j], 1) ? '1' : '0';
  757.             bit[2] = IsBit(g->gbits[t][j], 2) ? '1' : '0';
  758.             chm[0] = '0' + g->genome[t][j].exec;
  759.             chm[1] = '0' + g->genome[t][j].write;
  760.             chm[2] = '0' + g->genome[t][j].read;
  761.             fprintf(fp, "%-8s; %s %s %02x %3u\n", id[di].mn, chm, 
  762.                     bit, di, t);
  763.         }
  764.     }
  765. #endif /* PLOIDY > 1 */
  766. if (fp!= stdout) {fflush(fp);fclose(fp);}
  767. }
  768.  
  769. #ifdef IBM3090
  770. static unsigned char a2e[] = {
  771.     0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, 0026, 0005, 0045, 0013, 0014, 0015, 0016,
  772.     0017, 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, 0030, 0031, 0077, 0047, 0034, 0035,
  773.     0036, 0037, 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175, 0115, 0135, 0134, 0116, 0153,
  774.     0140, 0113, 0141, 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 0370, 0371, 0172, 0136,
  775.     0114, 0176, 0156, 0157, 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 0310, 0311, 0321,
  776.     0322, 0323, 0324, 0325, 0326, 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, 0347, 0350,
  777.     0351, 0112, 0340, 0132, 0137, 0155, 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 0210,
  778.     0211, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
  779.     0247, 0250, 0251, 0300, 0152, 0320, 0241, 0007, 0040, 0041, 0042, 0043, 0044, 0025, 0006,
  780.     0027, 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, 0060, 0061, 0032, 0063, 0064, 0065,
  781.     0066, 0010, 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, 0101, 0102, 0103, 0104, 0105,
  782.     0106, 0107, 0110, 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 0130, 0131, 0142, 0143,
  783.     0144, 0145, 0146, 0147, 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 0170,
  784.     0200, 0212, 0213, 0214, 0215, 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, 0237, 0240,
  785.     0252, 0253, 0254, 0255, 0256, 0257, 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 0270,
  786.     0271, 0272, 0273, 0274, 0275, 0276, 0277, 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
  787.     0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, 0356, 0357, 0372, 0373, 0374, 0375, 0376,
  788. 0377};
  789.  
  790. static unsigned char e2a[] = {
  791.     0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, 0227, 0215, 0216, 0013, 0014, 0015, 0016,
  792.     0017, 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, 0030, 0031, 0222, 0217, 0034, 0035,
  793.     0036, 0037, 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, 0210, 0211, 0212, 0213, 0214,
  794.     0005, 0006, 0007, 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, 0230, 0231, 0232, 0233,
  795.     0024, 0025, 0236, 0032, 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 0250, 0133,
  796.     0056, 0074, 0050, 0053, 0041, 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 0260, 0261,
  797.     0135, 0044, 0052, 0051, 0073, 0136, 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, 0270,
  798.     0271, 0174, 0054, 0045, 0137, 0076, 0077, 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
  799.     0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, 0303, 0141, 0142, 0143, 0144, 0145, 0146,
  800.     0147, 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, 0312, 0152, 0153, 0154, 0155, 0156,
  801.     0157, 0160, 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320, 0321, 0176, 0163, 0164, 0165,
  802.     0166, 0167, 0170, 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327, 0330, 0331, 0332, 0333,
  803.     0334, 0335, 0336, 0337, 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 0173, 0101, 0102,
  804.     0103, 0104, 0105, 0106, 0107, 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, 0175, 0112,
  805.     0113, 0114, 0115, 0116, 0117, 0120, 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, 0134,
  806.     0237, 0123, 0124, 0125, 0126, 0127, 0130, 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
  807.     0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, 0070, 0071, 0372, 0373, 0374, 0375, 0376,
  808. 0377};
  809.  
  810. Ascii2Ebcdic(s)
  811.     char *s;
  812. {
  813.     while (*s = a2e[*s])
  814.         s++;
  815. }
  816.  
  817. Ebcdic2Ascii(s)
  818.     char *s;
  819. {
  820.     while (*s = e2a[*s])
  821.         s++;
  822. }
  823.  
  824. #endif
  825.  
  826. void WritEcoB(bits, buf)
  827.     I32u bits;
  828.     I8s *buf;        /* changed by DAN */
  829. {
  830.     int i, j;
  831.     
  832.     if(!buf) return;
  833.     sprintf(buf,"EX      TC      TP      MF      MT      MB      ");
  834.     for (i = 0, j = 0; i < 6; i++, j = 0) {
  835.         if (IsBit(bits, 5 * i + 2))
  836.             buf[2+(i*8)+j++] = 's';
  837.         if (IsBit(bits, 5 * i + 3))
  838.             buf[2+(i*8)+j++] = 'd';
  839.         if (IsBit(bits, 5 * i + 4))
  840.             buf[2+(i*8)+j++] = 'o';
  841.         if (IsBit(bits, 5 * i + 5))
  842.             buf[2+(i*8)+j++] = 'f';
  843.         if (IsBit(bits, 5 * i + 6))
  844.             buf[2+(i*8)+j++] = 'h';
  845.     }
  846. }
  847.  
  848. void SetBit(seed, bit, value)
  849.     I32u *seed, bit, value;
  850. {
  851.     if (value)
  852.         (*seed) |= (ONE << bit);
  853.     else
  854.         (*seed) &= (~(ONE << bit));
  855. }
  856.  
  857. I16s id_compare(i,j)
  858. InstDef   *i,*j;
  859. {   return(i->op - j->op);
  860. }
  861.  
  862. void GetAMap(file)
  863.     I8s file[85];
  864. {   FILE  *afp;
  865.     char  data[85];
  866.     I32s  i, opc;
  867.  
  868.     if((afp = fopen(file,"r")) == NULL)
  869.     {   fprintf(stderr,"unable to open IMapFile  - %s", file);
  870.         exit(-666);
  871.     }
  872.     fgets(data, 84, afp);
  873.     i = opc = 0;
  874.     while (strlen(data) > 3)
  875.     {   if (((sscanf(data,"%*[^x]x%lx%*[^\"]\"%[^\"]", &opc, id[i].mn))
  876.             >= 2) && ((opc >= 0) && (opc < INSTNUM )))
  877.         {   id[i].op = opc;
  878.             if (!strcmp(id[i].mn, "nop0"))
  879.             {   Nop0 = id[i].op;
  880.                 NopS = Nop0 + Nop1;
  881.             }
  882.             if (!strcmp(id[i].mn, "nop1"))
  883.             {   Nop1 = id[i].op;
  884.                 NopS = Nop0 + Nop1;
  885.             }
  886.             i++;
  887.         }
  888.         if (fgets(data, 84, afp) == NULL)
  889.             break ;
  890.     }
  891.     fclose(afp);
  892.     qsort(id,INSTNUM, sizeof(InstDef), id_compare);
  893. }
  894.  
  895. I32s Hash(size, v)
  896.     I32s    size;
  897.     FpInst  v;
  898. {   I32s  h = 0;
  899.     I32s  i, j;
  900.  
  901.     for (i = 0; i < size; i++) 
  902. #if PLOIDY == 1
  903.         h = (3 * h + (v + i)->inst) % 277218551L; /* 277218551 is prime */
  904. #else /* PLOIDY > 1 */
  905.         for (j = 0; j < PLOIDY; j++)
  906.             h = (3 * h + (v + i)[j]->inst) % 277218551L;
  907. #endif /* PLOIDY > 1 */
  908.     return h;
  909. }
  910.